package controllers

import java.io.{File, RandomAccessFile}
import java.nio.file.Files

import command.CommandExec
import dao._
import javax.inject.Inject
import play.api.libs.json.{JsValue, Json}
import play.api.mvc.{AbstractController, ControllerComponents}
import tool.{FormTool, Resource, Tool}

import scala.concurrent.ExecutionContext.Implicits.global
import implicits.Implicits._
import play.api.cache.AsyncCacheApi
import service._
import shared.VarTool
import tool.Pojo.{CommandData, JunctionIdData}
import utils.Utils

import scala.io.Source

/**
 * Created by yz on 11/5/2020
 */
class SearchController @Inject()(cc: ControllerComponents, junctionDao: JunctionDao,
                                 fusionSymbolsDao: FusionSymbolsDao, fusionSymbolsService: FusionSymbolsService,
                                 modalSymbolsService: ModalSymbolsService, resource: Resource,
                                 gtexIndexDao: GtexIndexDao, pancancerIndexDao: PancancerIndexDao,
                                 queryLsJunctionDao: QueryLsJunctionDao, queryJunctionDao: QueryJunctionDao,
                                 queryFsJunctionDao: QueryFsJunctionDao, detailLsDao: DetailLsDao,
                                 detailBsDao: DetailBsDao, detailFsDao: DetailFsDao, junctionService: JunctionService,
                                 cache: AsyncCacheApi)(
                                  implicit val modeDao: ModeDao,
                                  implicit val junctionLocationDao: JunctionLocationDao,
                                  implicit val queryJunctionService: QueryJunctionService,
                                  implicit val gtexSupplementIndexDao: GtexSupplementIndexDao,
                                ) extends AbstractController(cc) {

  def toIndex = Action { implicit request =>
    Ok(views.html.search.index())
  }

  def detailInfoBefore = Action { implicit request =>
    val data = FormTool.detailForm.bindFromRequest().get
    Ok(views.html.search.detailInfo(data.junctionId, data.kind))
  }

  def getAllGeneSymbols = Action.async { implicit request =>
    queryJunctionService.selectAllGeneSymbols.map { x =>
      Ok(Json.toJson(x))
    }
  }

  def getAllChr = Action.async { implicit request =>
    cache.getOrElseUpdate("chrs")(junctionService.getAllChr).map { x =>
      Ok(Json.toJson(x))
    }
  }

  def getAllJunctionByGeneSymbol = Action.async { implicit request =>
    val data = FormTool.geneSymbolForm.bindFromRequest().get
    junctionDao.selectAll(data.geneSymbol).map { x =>
      val json = Utils.getJsonByTs(x)
      Ok(json)
    }
  }

  def getAllLsJunctionByGeneSymbol = Action.async { implicit request =>
    val data = FormTool.geneSymbolForm.bindFromRequest().get
    queryLsJunctionDao.selectAll(data.geneSymbol).map { x =>
      val json = Utils.getJsonByTs(x)
      Ok(json)
    }
  }

  def getAllBsJunctionByGeneSymbol = Action.async { implicit request =>
    val data = FormTool.geneSymbolForm.bindFromRequest().get
    queryJunctionDao.selectAll(data.geneSymbol).map { x =>
      val json = Utils.getJsonByTs(x)
      Ok(json)
    }
  }

  def getAllFsJunctionByGeneSymbol = Action.async { implicit request =>
    val data = FormTool.geneSymbolForm.bindFromRequest().get
    queryFsJunctionDao.selectAll(data.geneSymbol).map { x =>
      val json = Utils.getJsonByTs(x)
      Ok(json)
    }
  }

  def checkInFusionSymbols = Action.async { implicit request =>
    val data = FormTool.geneSymbolForm.bindFromRequest().get
    fusionSymbolsService.getAllSymbols.map { x =>
      val b = x.contains(data.geneSymbol)
      Ok(Json.toJson(b))
    }
  }

  def checkInModalSymbols = Action.async { implicit request =>
    val data = FormTool.geneSymbolForm.bindFromRequest().get
    modalSymbolsService.getAllSymbols.map { x =>
      val b = x.contains(data.geneSymbol)
      Ok(Json.toJson(b))
    }
  }

  def checkInGtex = Action.async { implicit request =>
    val data = FormTool.junctionIdForm.bindFromRequest().get
    junctionDao.select(data.junctionId).flatMap { row =>
      val location = row.junctionLocation
      gtexIndexDao.selectOp(location).zip(gtexSupplementIndexDao.selectOp(location))
    }.map { case (op, supplementOp) =>
      val b = op.isDefined || supplementOp.isDefined
      Ok(Json.toJson(b))
    }
  }

  def checkInTcga = Action.async { implicit request =>
    val data = FormTool.junctionIdForm.bindFromRequest().get
    junctionDao.select(data.junctionId).map { row =>
      val b = row.kind == "LS"
      Ok(Json.toJson(b))
    }
  }

  def generateGtexImage = Action.async { implicit request =>
    val startTime = System.currentTimeMillis()
    val data = FormTool.tcgaForm.bindFromRequest().get
    val junctionId = data.junctionId
    junctionDao.select(junctionId).flatMap { row =>
      Utils.logTime(startTime)
      val location = row.junctionLocation
      gtexIndexDao.selectOp(location).zip(gtexSupplementIndexDao.selectOp(location))
    }.map { case (indexOp, supplementIndexOp) =>
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val inputFile = new File(tmpDir, "2.csv")
      val (index, file) = if (indexOp.isDefined) {
        val index = indexOp.get
        val file = new File(Tool.gtexDataDir, s"GTEx_format_expr2.csv")
        (index, file)
      } else {
        val index = supplementIndexOp.get
        val file = new File(Tool.gtexDataDir, s"GTEx_exp_supplement.csv")
        (index, file)
      }
      val contentLines = {
        val randomFile = new RandomAccessFile(file, "r")
        randomFile.seek(index)
        val line = randomFile.readLine()
        randomFile.close()
        val tissues = (new File(Tool.gtexDataDir, "GTEx_tissue.txt")).lines
        val values = line.mySplit(",").drop(1)
        tissues.zip(values).map { case (tissue, value) =>
          List(tissue, value)
        }
      }

      (contentLines).toFile(inputFile)
      println("file generate:", Utils.getTime(startTime))

      val fileName = "GTEx_plot"
      val (pdfFile, pngFile) = if (data.logScale == "TRUE") {
        val pngFile = new File(tmpDir, s"${fileName}_log.png")
        val pdfFile = new File(tmpDir, s"${fileName}_log.pdf")
        (pdfFile, pngFile)
      } else {
        val pngFile = new File(tmpDir, s"${fileName}_noLog.png")
        val pdfFile = new File(tmpDir, s"${fileName}_noLog.pdf")
        (pdfFile, pngFile)
      }

      val command =
        s"""
           |Rscript ${Tool.rPath.unixPath}/GTEx_plot.R -jt ${inputFile.unixPath} -log ${data.logScale}
           |convert  -density 300 -background white -alpha remove -alpha off ${pdfFile.getAbsoluteFile.unixPath} ${pngFile.getAbsoluteFile.unixPath}
           |""".stripMargin
      val trueCommand = if (Utils.isWindows) command else command.conda()
      val commandExec = CommandExec().exec { b =>
        CommandData(tmpDir, trueCommand)
      }

      if (commandExec.isSuccess) {
        println("exec complete:", Utils.getTime(startTime))
        val base64 = pngFile.base64
        val pdfBase64 = pdfFile.base64
        Tool.deleteDirectory(tmpDir)
        Ok(Json.obj("valid" -> true, "base64" -> base64, "pdfBase64" -> pdfBase64))
      } else {
        Tool.deleteDirectory(tmpDir)
        Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
      }
    }

  }

  def getAllKind = Action.async { implicit request =>
    val data = FormTool.junctionIdForm.bindFromRequest().get
    junctionDao.select(data.junctionId).flatMap { x =>
      pancancerIndexDao.selectAllKind(x.junctionLocation)
    }.map { x =>
      Ok(Json.toJson(x))
    }
  }

  def png2pdf = Action {
    implicit request =>
      val startTime = System.currentTimeMillis()
      val data = FormTool.base64Form.bindFromRequest().get
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val inputFile = new File(tmpDir, "input.png")
      val outFile = new File(tmpDir, "out.pdf")
      data.base64.base642pngFile(inputFile)
      val command =
        s"""
           |convert ${inputFile.unixPath}  ${outFile.unixPath}
           |""".stripMargin
      val trueCommand = if (Utils.isWindows) command else command
      val commandExec = CommandExec().exec { b =>
        CommandData(tmpDir, trueCommand)
      }

      if (commandExec.isSuccess) {
        Ok(Json.obj("valid" -> true, "base64" -> outFile.base64))
      } else {
        Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
      }
  }

  def image2jpeg = Action {
    implicit request =>
      val startTime = System.currentTimeMillis()
      val data = FormTool.base64Form.bindFromRequest().get
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val inputFile = new File(tmpDir, "input.png")
      data.base64.base642pngFile(inputFile)
      val outFile = new File(tmpDir, "out.jpg")
      val command =
        s"""
           |convert ${inputFile.unixPath}  ${outFile.unixPath}
           |""".stripMargin
      val trueCommand = if (Utils.isWindows) command else command
      val commandExec = CommandExec().exec { b =>
        CommandData(tmpDir, trueCommand)
      }

      if (commandExec.isSuccess) {
        Ok(Json.obj("valid" -> true, "base64" -> outFile.base64))
      } else {
        Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
      }
  }

  def image2svg = Action {
    implicit request =>
      val startTime = System.currentTimeMillis()
      val data = FormTool.base64Form.bindFromRequest().get
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val imageType = FormTool.imageTypeForm.bindFromRequest().get.imageType
      val inputFile = imageType match {
        case "png" => val inputFile = new File(tmpDir, "input.png")
          data.base64.base642pngFile(inputFile)
        case "pdf" => val inputFile = new File(tmpDir, "input.pdf")
          data.base64.base642pdfFile(inputFile)
      }
      val outFile = new File(tmpDir, "out.svg")
      val command = imageType match {
        case "pdf" =>
          s"""
             |inkscape -l ${outFile.unixPath} ${inputFile.unixPath}
             |""".stripMargin
        case "png" =>
          s"""
             |convert ${inputFile.unixPath}  ${outFile.unixPath}
             |""".stripMargin
      }

      val trueCommand = if (Utils.isWindows) command else command
      val commandExec = CommandExec().exec { b =>
        CommandData(tmpDir, trueCommand)
      }

      if (commandExec.isSuccess) {
        Ok(Json.obj("valid" -> true, "base64" -> outFile.base64))
      } else {
        Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
      }
  }

  def generateSurvivalImage = Action.async {
    implicit request =>
      val startTime = System.currentTimeMillis()
      val data = FormTool.survivalForm.bindFromRequest().get
      val junctionId = data.junctionId
      val simpleCsvDir = new File(Tool.pancancerDataDir, "simple_csv")
      val infoDir = new File(Tool.survivalDataDir, "info")
      junctionDao.select(junctionId).flatMap { row =>
        Utils.logTime(startTime)
        val location = row.junctionLocation
        pancancerIndexDao.selectAll(location, data.kind)
      }.map { rows =>
        Utils.logTime("index select", startTime)
        val tmpDir = Tool.createTempDirectory("tmpDir")
        val inputFile = new File(tmpDir, "jt.csv")
        val contentLines = rows.toList.flatMap { row =>
          val kind = row.kind
          val file = new File(simpleCsvDir, s"${row.kind}.csv")
          val index = row.index
          val randomFile = new RandomAccessFile(file, "r")
          randomFile.seek(index)
          val line = randomFile.readLine()
          randomFile.close()
          val values = line.mySplit(",").drop(1)
          val infoFile = new File(infoDir, s"${kind}.info")
          val infos = infoFile.csvLines
          infos.zip(values).map { case (infos, value) =>
            infos ::: List(value)
          }
        }

        (contentLines).toFile(inputFile)
        println("file generate:", Utils.getTime(startTime))

        val fileName = "surv_plot"
        val pngFile = new File(tmpDir, s"${fileName}.png")
        val pdfFile = new File(tmpDir, s"${fileName}.pdf")
        val command =
          s"""
             |Rscript ${Tool.rPath.unixPath}/survival_plot.R -jt ${inputFile.unixPath}  -c ${data.kind} -s ${data.methods} -m ${data.groupCutoff}
             |convert  -density 300 -background white -alpha remove -alpha off ${pdfFile.getAbsoluteFile.unixPath} ${pngFile.getAbsoluteFile.unixPath}
             |""".stripMargin
        val trueCommand = if (Utils.isWindows) command else command.conda()
        val commandExec = CommandExec().exec {
          b =>
            CommandData(tmpDir, trueCommand)
        }

        if (commandExec.isSuccess) {
          println("exec complete:", Utils.getTime(startTime))
          val base64 = pngFile.base64
          val pdfBase64 = pdfFile.base64
          Tool.deleteDirectory(tmpDir)
          Ok(Json.obj("valid" -> true, "base64" -> base64, "pdfBase64" -> pdfBase64))
        } else {
          Tool.deleteDirectory(tmpDir)
          Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
        }
      }

  }

  def generateTcgaImage = Action.async {
    implicit request =>
      val startTime = System.currentTimeMillis()
      val data = FormTool.tcgaForm.bindFromRequest().get
      val junctionId = data.junctionId
      val simpleCsvDir = new File(Tool.pancancerDataDir, "simple_csv")
      junctionDao.select(junctionId).flatMap { row =>
        Utils.logTime(startTime)
        val location = row.junctionLocation
        pancancerIndexDao.selectAll(location)
      }.map { rows =>
        Utils.logTime("index select", startTime)
        val tmpDir = Tool.createTempDirectory("tmpDir")
        val jtFile = new File(tmpDir, "jt.csv")

        val contentLines = rows.toList.flatMap { row =>
          val file = new File(simpleCsvDir, s"${row.kind}.csv")
          val index = row.index
          val randomFile = new RandomAccessFile(file, "r")
          randomFile.seek(index)
          val line = randomFile.readLine()
          randomFile.close()
          val values = line.mySplit(",").drop(1)
          val classes = (new File(simpleCsvDir, s"${row.kind}.class")).lines
          classes.zip(values).map {
            case (curClass, value) =>
              List(value, curClass, row.kind)
          }
        }

        val curTypes = rows.map(_.kind)
        val needFillContents = VarTool.types.filter { x =>
          !curTypes.contains(x)
        }.flatMap { kind =>
          val classes = (new File(simpleCsvDir, s"${kind}.class")).lines
          classes.map { curClass =>
            List("0", curClass, kind)
          }
        }

        (contentLines ::: needFillContents).toFile(jtFile)
        println("file generate:", Utils.getTime(startTime))
        val (pdfFile, pngFile) = if (data.logScale == "TRUE") {
          val pngFile = new File(tmpDir, "pancancer_plot_log.png")
          val pdfFile = new File(tmpDir, "pancancer_plot_log.pdf")
          (pdfFile, pngFile)
        } else {
          val pngFile = new File(tmpDir, "pancancer_plot_noLog.png")
          val pdfFile = new File(tmpDir, "pancancer_plot_noLog.pdf")
          (pdfFile, pngFile)
        }

        val command =
          s"""
             |Rscript ${Tool.rPath.unixPath}/pancancer_plot.R -jt ${jtFile.unixPath} -log ${data.logScale}
             |convert  -density 300 -background white -alpha remove -alpha off ${pdfFile.getAbsoluteFile.unixPath} ${pngFile.getAbsoluteFile.unixPath}
             |""".stripMargin
        val trueCommand = if (Utils.isWindows) command else command.conda()
        val commandExec = CommandExec().exec {
          b =>
            CommandData(tmpDir, trueCommand)
        }

        if (commandExec.isSuccess) {
          println("exec complete:", Utils.getTime(startTime))
          val base64 = pngFile.base64
          val pdfBase64 = pdfFile.base64
          Tool.deleteDirectory(tmpDir)
          Ok(Json.obj("valid" -> true, "base64" -> base64, "pdfBase64" -> pdfBase64))
        } else {
          Tool.deleteDirectory(tmpDir)
          Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
        }
      }

  }

  def generateBoxplotImage = Action.async {
    implicit request =>
      val startTime = System.currentTimeMillis()
      val data = FormTool.boxplotForm.bindFromRequest().get
      val junctionId = data.junctionId
      val simpleCsvDir = new File(Tool.pancancerDataDir, "simple_csv")
      junctionDao.select(junctionId).flatMap { row =>
        Utils.logTime(startTime)
        val location = row.junctionLocation
        pancancerIndexDao.selectAll(location, data.kinds)
      }.map { rows =>
        val tmpDir = Tool.createTempDirectory("tmpDir")
        val inputFile = new File(tmpDir, "jt.csv")
        val contentLines = rows.toList.flatMap { row =>
          val file = new File(simpleCsvDir, s"${row.kind}.csv")
          val index = row.index
          val randomFile = new RandomAccessFile(file, "r")
          randomFile.seek(index)
          val line = randomFile.readLine()
          randomFile.close()
          val values = line.mySplit(",").drop(1)
          val classes = (new File(simpleCsvDir, s"${row.kind}.class")).lines
          classes.zip(values).map {
            case (curClass, value) =>
              List(value, curClass, row.kind)
          }
        }

        (contentLines).toFile(inputFile)
        println("file generate:", Utils.getTime(startTime))
        val logScale = data.logScale.map(_ => "TRUE").getOrElse("FALSE")

        val fileName = "cancer_boxplot"
        val (pdfFile, pngFile) = if (logScale == "TRUE") {
          val pngFile = new File(tmpDir, s"${fileName}_log.png")
          val pdfFile = new File(tmpDir, s"${fileName}_log.pdf")
          (pdfFile, pngFile)
        } else {
          val pngFile = new File(tmpDir, s"${fileName}_noLog.png")
          val pdfFile = new File(tmpDir, s"${fileName}_noLog.pdf")
          (pdfFile, pngFile)
        }
        val command =
          s"""
             |Rscript ${Tool.rPath.unixPath}/cancer_boxplot.R -jt ${inputFile.unixPath}  -log ${logScale}
             |convert  -density 300 -background white -alpha remove -alpha off ${pdfFile.getAbsoluteFile.unixPath} ${pngFile.getAbsoluteFile.unixPath}
             |""".stripMargin
        val trueCommand = if (Utils.isWindows) command else command.conda()
        val commandExec = CommandExec().exec {
          b =>
            CommandData(tmpDir, trueCommand)
        }

        if (commandExec.isSuccess) {
          println("exec complete:", Utils.getTime(startTime))
          val base64 = pngFile.base64
          val pdfBase64 = pdfFile.base64
          Tool.deleteDirectory(tmpDir)
          Ok(Json.obj("valid" -> true, "base64" -> base64, "pdfBase64" -> pdfBase64))
        } else {
          Tool.deleteDirectory(tmpDir)
          Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
        }
      }

  }

  def getJunctionById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      junctionDao.select(data.junctionId).map {
        x =>
          val json = Utils.getJsonByT(x)
          Ok(json)
      }
  }

  def getBsJunctionById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      queryJunctionDao.select(data.junctionId).map {
        x =>
          val json = Utils.getJsonByT(x)
          Ok(json)
      }
  }

  def getFsJunctionById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      queryFsJunctionDao.select(data.junctionId).map {
        x =>
          val json = Utils.getJsonByT(x)
          Ok(json)
      }
  }

  def getLsJunctionById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      queryLsJunctionDao.select(data.junctionId).map {
        x =>
          val json = Utils.getJsonByT(x)
          Ok(json)
      }
  }

  def getDetailLsById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      detailLsDao.select(data.junctionId).map { x =>
        val json = Utils.getJsonByT(x)
        Ok(json)
      }
  }

  def getDetailBsById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      detailBsDao.select(data.junctionId).map { x =>
        val json = Utils.getJsonByT(x)
        Ok(json)
      }
  }

  def getDetailFsById = Action.async {
    implicit request =>
      val data = FormTool.junctionIdForm.bindFromRequest().get
      detailFsDao.select(data.junctionId).map { x =>
        val json = Utils.getJsonByT(x)
        Ok(json)
      }
  }

  def keywordSearch = Action.async {
    implicit request =>
      val data = FormTool.keywordForm.bindFromRequest().get
      val geneSymbols = data.keyword.mySplit("\n").flatMap(_.mySplit(","))
      junctionDao.selectAll(geneSymbols).map {
        x =>
          val json = Utils.getJsonByTs(x)
          Ok(json)
      }
  }

  def searchResultBefore = Action {
    implicit request =>
      val data = FormTool.keywordForm.bindFromRequest().get
      val newKeyword = data.keyword.split(",").distinct.mkString(",")
      Ok(views.html.search.searchResult(newKeyword))
  }

  def advancedFilter = Action.async { implicit request =>
    val data = FormTool.advancedFilterForm.bindFromRequest().get
    junctionLocationDao.selectAllJunctionId(data).map { junctionIds =>
      val num = 30000
      junctionIds.grouped(num).toList.flatMap { eachJunctionIds =>
        val f = junctionDao.selectAll(data, eachJunctionIds)
        Utils.execFuture(f)
      }
    }.map { x =>
      val fsJunctionIds = x.filter(_.kind == "FS").map(_.junctionId)
      val f = queryFsJunctionDao.selectAll(fsJunctionIds).map { rows =>
        rows.flatMap { row =>
          List(row.geneSymbol1, row.geneSymbol2)
        }
      }
      val fsGeneSymbols = Utils.execFuture(f)
      val otherSymbols = x.filterNot(_.kind == "FS").map(_.geneSymbol)
      val symbols = (fsGeneSymbols ::: otherSymbols).distinct.sorted
      println(symbols.size)
      Ok(Json.toJson(symbols))
    }
  }

  def generateGenePatternImage = Action {
    implicit request =>
      val data = FormTool.geneModalForm.bindFromRequest().get
      val geneSymbol = data.geneSymbol
      val dataDir = new File(Tool.genePatternDataDir, geneSymbol)
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val bsFile = new File(dataDir, s"${
        geneSymbol
      }_BS.bed")
      val otherArgs = data.method match {
        case "all" => List("")
        case "specific" => List("-TS", "TS")
        case "unannotated" => List("-anno", "un")
      }
      val otherArg = otherArgs.mkString(" ")
      val command = if (bsFile.exists()) {
        s"""
           |python3 ${
          Tool.pyPath.unixPath
        }/splicev.py -bsj ${
          dataDir.unixPath
        }/${
          geneSymbol
        }_BS.bed -sj ${
          dataDir.unixPath
        }/${
          geneSymbol
        }_LS.bed -gtf ${
          dataDir.unixPath
        }/${
          geneSymbol
        }.gtf -g ${
          geneSymbol
        } -category all -format PNG ${otherArg} -c gray
           |""".stripMargin
      } else {
        s"""
           |python3 ${
          Tool.pyPath.unixPath
        }/splicev.py -sj ${
          dataDir.unixPath
        }/${
          geneSymbol
        }_LS.bed -gtf ${
          dataDir.unixPath
        }/${
          geneSymbol
        }.gtf  -g ${
          geneSymbol
        } -category all -format PNG ${otherArg} -c gray
           |""".stripMargin
      }
      val trueCommand = if (Utils.isWindows) command.conda("py27") else command
      val commandExec = CommandExec().exec {
        b =>
          CommandData(tmpDir, trueCommand)
      }
      if (commandExec.isSuccess) {
        val pngFile = new File(tmpDir, s"${data.geneSymbol}.png")
        val base64 = pngFile.base64
        Tool.deleteDirectory(tmpDir)
        Ok(Json.obj("valid" -> true, "base64" -> base64))
      } else {
        Tool.deleteDirectory(tmpDir)
        Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
      }
  }

  def generateGeneFusionImage = Action {
    implicit request =>
      val data = FormTool.geneSymbolForm.bindFromRequest().get
      val geneSymbol = data.geneSymbol
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val pdfFile = new File(tmpDir, s"${geneSymbol}.pdf")
      val pngFile = new File(tmpDir, s"${geneSymbol}.png")
      val command =
        s"""
           |Rscript ${Tool.rPath.unixPath}/fusion_plot.R --b ${Tool.geneFusionDataDir.unixPath}/gene_fusion.bed --g ${geneSymbol} --o ${pdfFile.unixPath}
           |convert  -density 300 -background white -alpha remove -alpha off ${pdfFile.getAbsoluteFile.unixPath} ${pngFile.getAbsoluteFile.unixPath}
           """.stripMargin
      val trueCommand = if (Utils.isWindows) command else command.conda()
      val commandExec = CommandExec().exec {
        b =>
          CommandData(tmpDir, trueCommand)
      }
      if (commandExec.isSuccess) {
        val base64 = pngFile.base64
        val pdfBase64 = pdfFile.base64
        Tool.deleteDirectory(tmpDir)
        Ok(Json.obj("valid" -> true, "base64" -> base64, "pdfBase64" -> pdfBase64))
      } else {
        Tool.deleteDirectory(tmpDir)
        Ok(Json.obj("valid" -> false, "message" -> commandExec.errorInfo))
      }
  }

  def getGenePatternImage = Action {
    implicit request =>
      val data = FormTool.geneSymbolForm.bindFromRequest().get
      val dir = FormTool.dirForm.bindFromRequest().get.dir
      val geneSymbol = data.geneSymbol
      val ifModifiedSinceStr = request.headers.get(IF_MODIFIED_SINCE)
      val dataDir = new File(Tool.dataDir, dir)
      val tmpDir = new File(dataDir, geneSymbol)
      val file = new File(tmpDir, s"${
        geneSymbol
      }.png")
      val lastModifiedStr = file.lastModified().toString
      val MimeType = "image/png"
      val byteArray = Files.readAllBytes(file.toPath)
      if (ifModifiedSinceStr.isDefined && ifModifiedSinceStr.get == lastModifiedStr) {
        NotModified
      } else {
        Ok(byteArray).as(MimeType).withHeaders(LAST_MODIFIED -> file.lastModified().toString)
      }
  }


}
